package cn.lyjuan.payment.third.base.model.app.check;

import cn.lyjuan.base.util.DigestUtils;
import cn.lyjuan.base.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class AppCheck
{
    /**
     * 验证MD5签名
     *
     * @param params
     * @param md5Key
     * @return
     */
    public static boolean checkSign(Map<String, String> params, String md5Key)
    {
        if (null == params || params.size() < 1) return false;
        if (StringUtils.isNull(md5Key))
            throw new RuntimeException("sign md5 key cannot be null");

        String peer = params.get("sign");
        if (StringUtils.isNull(peer))
            return false;

        // 拼接参数
        String sign = sign(params, md5Key);

        return sign.equalsIgnoreCase(peer);
    }

    /**
     * 参数签名
     * @param params
     * @param md5Key
     * @return
     */
    public static String sign(Map<String, String> params, String md5Key)
    {
        // 拼接参数
        String str = appendParams(params);
        try
        {
            String sign = DigestUtils.md5UpperCase(str + md5Key, "UTF-8");
            return sign;
        } catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }

    /**
     * 按字典序排列参数，并使用html form参数形式拼接
     *
     * @param params
     * @return
     */
    private static String appendParams(Map<String, String> params)
    {
        StringBuilder sb = new StringBuilder();

        // 排序
        List<String> names = new ArrayList<>(params.size());
        for (String n : params.keySet())
        {
            if (StringUtils.isNull(n)) continue;
            if ("sign".equalsIgnoreCase(n)) continue;

            names.add(n);
        }

        Collections.sort(names);
        String val = null;
        for (String n : names)
        {
            val = params.get(n);
            if (StringUtils.isNull(val)) continue;

            sb.append(n + "=" + val).append("&");
        }

        if (sb.toString().length() > 0) sb.delete(sb.length() - 1, sb.length());

        return sb.toString();
    }
}
